package com.cheetah.start.common.exception;

import cn.hutool.core.util.StrUtil;
import com.cheetah.start.common.base.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 统一异常捕获
 *
 * @author xjhmwj
 * @date 2021/1/8 10:19
 */
@Slf4j
@ControllerAdvice
public class GlobaException {

    /**
     * 数据校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public Result bindException(BindException e) {
        log.error("数据校验出现问题:[{}]，异常类型:[{}]", e.getMessage(), e.getClass());
        BindingResult bindingResult = e.getBindingResult();
        List<ObjectError> list = bindingResult.getAllErrors();
        StringBuilder builder = new StringBuilder();
        list.forEach(x -> {
            FieldError error = (FieldError) x;
            builder.append(error.getDefaultMessage());
            builder.append("<br/>");
        });
        return Result.failure(builder.toString());
    }


    /**
     * 单个参数异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseBody
    public Result constraintViolationException(ConstraintViolationException e) {
        log.error("参数异常:[{}]", e);
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining("<br/>"));
        return Result.failure(message);
    }

    /**
     * 请求类型错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public Result httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error("请求类型异常:[{}]", e.getMessage());
        return Result.failure("请求类型错误");
    }

    /**
     * 最大上传大小超
     *
     * @param e e
     * @return {@link Result}
     */
    @ExceptionHandler(value = MaxUploadSizeExceededException.class)
    @ResponseBody
    public Result maxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        log.error("上传文件大小超出限制:[{}]", e.getMessage());
        return Result.failure("上传文件大小超出限制");
    }


    /**
     * 第三方错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = CheetahException.class)
    @ResponseBody
    public Result cheetahException(CheetahException e) {
        log.error("项目异常:[{}]", e.getMessage());
        return Result.failure("项目异常:[" + e.getMessage() + "]");
    }


    /**
     * 需要登录异常
     *
     * @param e e
     * @return {@link Result}
     */
    @ExceptionHandler(value = NeedLoginException.class)
    public ModelAndView needLoginException(NeedLoginException e) {
        log.error("需要登录异常:[{}]", e.getMessage());
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("/jumpLogin");
        return modelAndView;
    }

    /**
     * 文件上传异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = MyFileException.class)
    @ResponseBody
    public Result myFileException(MyFileException e) {
        log.error("文件上传异常:[{}]", e.getMessage());
        return Result.failure("文件上传异常:[" + e.getMessage() + "]");
    }

    /**
     * 运行异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = RuntimeException.class)
    @ResponseBody
    public Result runtimeException(RuntimeException e, HttpServletRequest request) {
        e.printStackTrace();
        log.error("runtime异常:[{}]", e.getMessage());
        String requestUri = request.getRequestURI();
        String queryString = request.getQueryString();
        log.error("异常接口地址:[{}]", requestUri);
        log.error("异常参数:[{}]", queryString);
        return Result.failure(StrUtil.format("运行异常:{},接口地址:{}", e.getMessage(), requestUri));
    }

    /**
     * 异常
     *
     * @param e e
     * @return {@link Result}
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result exception(Exception e, HttpServletRequest request) {
        e.printStackTrace();
        log.error("未知异常:[{}]", e.getMessage());
        String requestUri = request.getRequestURI();
        String queryString = request.getQueryString();
        log.error("异常接口地址:[{}]", requestUri);
        log.error("异常参数:[{}]", queryString);
        return Result.failure(StrUtil.format("异常:{},接口地址:{}", e.getMessage(), requestUri));
    }
}


